package kkk;

import java.awt.Color;
import robocode.HitWallEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;

/**
 * Strafes left and right to dodge bullets while constantly firing at closest opponent.
 * 
 * @author Kyle Kakinami
 */
public class Strafer extends Robot {

  private double closestEnemy;
  private double targetBearing;
  private double targetVelocity;
  private double scannedDistance;
  private double scannedVelocity;
  private double scannedBearing;
  private double alternator = -1;

  /**
   * Runs robot.
   * 
   */
  public void run() {
    setColors(Color.black, Color.magenta, Color.black);

    // Battle field dimensions.
    double gridW = this.getBattleFieldWidth();
    double gridH = this.getBattleFieldHeight();

    // Find the max possible distance for the given battlefield.
    double wSquared = Math.pow(gridW, 2);
    double hSquared = Math.pow(gridH, 2);
    double maxDistance = Math.sqrt(wSquared + hSquared) + 1;
    double offset;

    // Set radar movement independent from robot movement.
    setAdjustRadarForRobotTurn(true);

    turnGunRight(-90);

    // Scan for targets, square up, and fire.
    while (true) {
      turnRadarRight(360);
      turnRight(targetBearing + 90);
      offset = closestEnemy / 13;
      
      // Fire away at stationary target.
      if (targetVelocity == 0) {
        fire(proportionalFire(closestEnemy, maxDistance));
      }
      // Offset aim at moving targets.
      else {
        offset *= alternator;
        turnRight(offset);
        fire(proportionalFire(closestEnemy, maxDistance));
      }

      // Larger strafes when enemies get too close.
      if (closestEnemy < 50) {
        ahead(closestEnemy / 3 + 100 * alternator);
        alternator *= -1;
      }
      // regular strafes based on target distance.
      else {
        ahead(closestEnemy / 3 * alternator);
        alternator *= -1;
      }


      closestEnemy = maxDistance;
    }
  }

  /**
   * Gets information about scanned robot.
   * 
   * @param e Scanned robot
   */
  public void onScannedRobot(ScannedRobotEvent e) {
    getScannedInfo(e);
    if (scannedDistance < closestEnemy) {
      closestEnemy = scannedDistance;
      targetBearing = scannedBearing;
      targetVelocity = scannedVelocity;
    }
  }

  /**
   * Handles hitting walls.
   * 
   * @param e hit wall event
   */
  public void onHitWall(HitWallEvent e) {
    turnRight(90);
    ahead(closestEnemy / 2);
  }

  /**
   * Gets important data from scanned robot.
   * 
   * @param e Scanned robot
   */
  public void getScannedInfo(ScannedRobotEvent e) {
    scannedDistance = e.getDistance();
    scannedVelocity = e.getVelocity();
    scannedBearing = e.getBearing();
  }

  /**
   * Changes the power based on distance to closest enemy.
   * 
   * @param closestEnemy    distance to closest enemy.
   * @param maxDistance     max distance in battlefield.
   * @return  porportional fire power.
   */
  public double proportionalFire(double closestEnemy, double maxDistance) {
    double proportion = closestEnemy / maxDistance;

    // Minimum firepower = 0.1, Maximum firepower: 3.0.
    return (3.0 * (1 - proportion));
  }
}
